'use strict';

const Olt = require("./OLT");
const snmp = require('net-snmp');
const common = require('../common')
const net = require('net');
const ulid  = require("../public/ulid");
class XGLOLT extends Olt {
  constructor(options) {
    super(options);
  }
  async getOltInformation(){
      return new Promise((resolve, reject) => {
        let olt = {
            systemName: "",
            serialNumber: "",
            hardwareVersion: "",
            softwareVersion: "",
            macAddress: "",
            softwareCreatedTime: "",
            systemTime: "",
            runningTime: "",
            cpuUsage: 0,
            memoryUsage: 0,
            licenseLimit: "",
            licenseTime: "",
        };
        let oids = [
            '1.3.6.1.2.1.1.5.0',//systemName
            '1.3.6.1.2.1.1.3.0',//running time
            '1.3.6.1.2.1.1.1.0',//hardwareVersion
            '1.3.6.1.2.1.1.1.0',//softwareVersion
        ];
        let session = snmp.createSession(this.options.ip, this.options.community, this.options);
        session.get(oids, function (error, varbinds) {
            if (error) {
                reject(error);
            } else {
                for (let i = 0; i < varbinds.length; i++) {
                    if (!snmp.isVarbindError(varbinds[i])) {
                        if (varbinds[i].oid == oids[0]) {
                            olt.systemName = varbinds[i].value.toString();
                        }
                        if (varbinds[i].oid == oids[1]) {
                            olt.runningTime = varbinds[i].value.toString();
                        }
                        if(varbinds[i].oid == oids[2]){
                          olt.hardwareVersion = varbinds[i].value.toString();
                        }
                        if(varbinds[i].oid == oids[3]){
                          olt.softwareVersion = varbinds[i].value.toString();
                        }
                    }
                }
                resolve(olt);
            }
            session.close();
        });
    });
  }
  async XGLTestConnection(){
    return new Promise((resolve, reject) => {
        let username = this.options.username;
        let password = this.options.password;
        let socketclient = net.createConnection({
          host: this.options.ip,
          port: this.options.tPort || 23,
        }, function () {
          // console.log('connected');
        })
        let step = 0;
        socketclient.on("data", function (data) {
          let info = data.toString();
          if (step == 2) {
            if (info.indexOf('Username or password error') != -1) {
              // console.log('登录失败');
              socketclient.destroy();
              resolve(false);
            } else {
              // console.log('登录成功');
              socketclient.destroy();
              resolve(true);
            }
          }
          if (info.indexOf('Username') != -1) {
            step++;
            socketclient.write(`${username}\r\n`);
          }
          if (info.indexOf('Password') != -1) {
            step++;
            socketclient.write(`${password}\r\n`);
          }
          //console.log(`receive data : ${data}`);
        });
  
        socketclient.on("close", function () {
          // console.log('close');
        });
  
        socketclient.on("error", function (err) {
          // console.log(err);
          resolve(false);
        });
      })
  }
  async GetCommunity_XGL(me){
    return new Promise(async (resolve, reject) => {
        let addr = this.options.ip + ":" + this.options.tPort;
        //组装模板变量
        let view = {
          username: this.options.username,
          password: this.options.password,
          prompt: this.options.systemName,
          ManagementPassword: this.options.managementPassword,
        };
        try {
          let resultArr = await common.run_EX(addr, {
            oltType: "XINGELIN",
            mountPoint: "GET_COMMUNITY",
            oltHardVersion: "NONE",
            view,
          },null,me);
          let msg = resultArr[0];
          let arr = msg.split('\n')
          arr.pop()
          let result = [];
          for(var i =4;i<arr.length;i++){
            result.push({
              index:arr[i].replace(/\s+/g, "|").split("|")[0],
              community:arr[i].replace(/\s+/g, "|").split("|")[1]
            })
          }
          resolve(result);
        } catch (error) {
          resolve(null);
        }
      });
  }
  async DeleteCommunity_XGL(CommunityArr,me){
    return new Promise(async (resolve, reject) => {
      let addr = this.options.ip + ":" + this.options.tPort;
      let view = {
        username: this.options.username,
        password: this.options.password,
        prompt: this.options.systemName,
        ManagementPassword: this.options.managementPassword,
        CommunityArr: CommunityArr
      }
      try {
        let resultArr = await common.run_EX(addr, {
          oltType: 'XINGELIN',
          mountPoint: 'DELETE_COMMUNITY',
          oltHardVersion: "NONE",
          view
        },null,me)
        resolve(true)
      } catch (error) {
        reject(error)
      }
    });
  }
  async SetCommunity_XGL(rocommunity, rwcommunity ,me){
    return new Promise(async (resolve, reject) => {
      let addr = this.options.ip + ":" + this.options.tPort;
      let view = {
        username: this.options.username,
        password: this.options.password,
        prompt: this.options.systemName,
        ManagementPassword: this.options.managementPassword,
        rocommunity,
        rwcommunity,
      }
      try {
        let resultArr = await common.run_EX(addr, {
          oltType: 'XINGELIN',
          mountPoint: 'MODIFY_COMMUNITY',
          oltHardVersion: "NONE",
          view
        },null,me)
        resolve(true)
      } catch (error) {
        resolve(false)
      }
    });
  }
  async getPonPortList(){
    var maxRepetitions = 20;
      var oid = "1.3.6.1.2.1.2.2";
      var columns = [2,7];
      return new Promise((resolve,reject) =>{
        let session = snmp.createSession(this.options.ip, this.options.community, this.options);
        session.tableColumns(oid,columns,maxRepetitions,function(error,table){
          if (error) {
              return reject(error);
          } else {
              return resolve(table);
          }
        })
      })
  }
  async getUplinkSpeedAndVlan(arr,oltHardVersion,me){
    return new Promise(async(resolve,reject) =>{
      let addr = this.options.ip + ":" + this.options.tPort;
      let view = {
        username: this.options.username,
        password: this.options.password,
        prompt: this.options.systemName,
        ManagementPassword: this.options.managementPassword,
        arr
      }
      try {
        let resultArr = await common.run_EX(addr, {
          oltType: 'XINGELIN',
          mountPoint: 'GET_UPLINK_SPEED_AND_VLAN',
          oltHardVersion,
          view
        },null,me)
        resultArr.shift()
        resultArr.forEach((item,index) =>{
          let result = item.split('\n')
          result.shift()
          result.pop()
          result.pop()
          let Port = result[0].indexOf('Port')
          let Desc = result[0].indexOf('Desc')
          let Link = result[0].indexOf('Link')
          let shutdn = result[0].indexOf('shutdn')
          let Speed = result[0].indexOf('Speed')
          let Pri = result[0].indexOf('Pri')
          let PVID = result[0].indexOf('PVID')
          let Mode = result[0].indexOf('Mode')
          let TagVlan = result[0].indexOf('TagVlan')
          let UtVlan = result[0].indexOf('UtVlan')
          let linkResult = result[1].substring(Link,shutdn).trim()
          if(linkResult == 'up'){
            arr[index].LinkStatus = 1
          }else{
            arr[index].LinkStatus = 2
          }
          arr[index].Speed = result[1].substring(Speed,Pri).trim()
          let UnTagvlan = result[1].substring(PVID,Mode).trim()
          if(UnTagvlan == '1'){
            arr[index].UnTagvlan = ''
          }else{
            arr[index].UnTagvlan = UnTagvlan
          }
          let str = result[1].substring(TagVlan,UtVlan).trim()
          if(result.length >= 3){
            for(var i = 2;i<result.length;i++){
              str += result[i].trim()
            }
          }
          console.log(str)
          let res = str.split(',')
          let arr2 = []
          res.forEach(item =>{
            if(item != '1'){
              arr2.push(item)
            }
          })
          arr[index].Tagvlan = arr2.toString()
        })
        resolve(arr)
      } catch (error) {
        reject(error)
      }
    })
  }
  async getVlanTable(oltHardVersion,me){
    return new Promise(async (resolve, reject) => {
      let addr = this.options.ip + ":" + this.options.tPort;
      let view = {
        username: this.options.username,
        password: this.options.password,
        prompt: this.options.systemName,
        ManagementPassword: this.options.managementPassword,
      }
      try {
        let resultArray = []
        let resultArr = await common.run_EX(addr, {
          oltType: 'XINGELIN',
          mountPoint: 'GET_VLAN',
          oltHardVersion,
          view
        },null,me)
        let msg = resultArr[0].split('\n')
        for(var i=2;i<msg.length-2;i++){
          let params = msg[i].replace(/\s+/g, '|').split('|')
          resultArray.push({
            VlanID: params[0],
            Memo: params[0],
            vlanTagPort: "",
            vlanUntagPort: "",
            vlanRowStatus: "",
          })
        }
        resolve(resultArray);
      } catch (error) {
        reject(error)
      }
    });
  }
  async getmacTable_XGL(oltHardVersion,me){
    return new Promise(async (resolve, reject) => {
      let addr = this.options.ip + ":" + this.options.tPort;
      let view = {
        username: this.options.username,
        password: this.options.password,
        prompt: this.options.systemName,
        ManagementPassword: this.options.managementPassword,
      }
      try {
        let resultArray = []
        let resultArr = await common.run_EX(addr, {
          oltType: 'XINGELIN',
          mountPoint: 'MAC_LIST',
          oltHardVersion,
          view
        },null,me)
        let msg = resultArr[0].split('\n')
        for(var i =2;i<msg.length-2;i++){
          let params = msg[i].replace(/\s+/g, '|').split('|')
          resultArray.push({
            Mac:params[0].replace(/\:/g,'-'),
            VlanID:params[1],
            PhysicalPort:params[2],
            Type:params[3]
          })
        }
        resolve(resultArray);
      } catch (error) {
        reject(error)
      }
    });
  }
  async setVlans_XGL(vlanStart,vlanEnd,oltHardVersion,me){
    return new Promise(async (resolve, reject) => {
      let addr = this.options.ip + ":" + this.options.tPort;
      let view = {
        username: this.options.username,
        password: this.options.password,
        prompt: this.options.systemName,
        ManagementPassword: this.options.managementPassword,
        vlanStart: vlanStart,
        vlanEnd: vlanEnd
      }
      try {
        let resultArr = await common.run_EX(addr, {
          oltType: "XINGELIN",
          mountPoint: "SET_VLAN",
          oltHardVersion,
          view,
        },null,me);
        resolve(true)
      } catch (error) {
        reject(error);
      }
    })
  }
  async deleteVlan_XGL(vlanID,oltHardVersion,me){
    return new Promise(async (resolve, reject) => {
      let addr = this.options.ip + ":" + this.options.tPort
      let view = {
          username: this.options.username,
          password: this.options.password,
          prompt: this.options.systemName,
          ManagementPassword: this.options.managementPassword,
          vlanID
      }
      try {
        let fn = function(msg){
          if(msg.indexOf(`can't be deleted`) != -1){
            return {result:false,message:msg.split('\r\n')[1]}
          }else{
            return{result:true}
          }
        }
        let resultArr = await common.run_EX(addr, {
            oltType: 'XINGELIN',
            mountPoint: 'DELETE_VLAN',
            oltHardVersion,
            view},fn,me)
        if(resultArr.length!= 0){
          reject(resultArr)
        }else{
          resolve(true)
        }
      } catch (error) {
        reject(error)
      }
    });
  }
  async getLineProfile(oltHardVersion,me){
    return new Promise(async (resolve, reject) => {
      let addr = this.options.ip + ":" + this.options.tPort
      let view = {
          username: this.options.username,
          password: this.options.password,
          prompt: this.options.systemName,
          ManagementPassword: this.options.managementPassword,
      }
      try {
        let result = []
        let resultArr = await common.run_EX(addr, {
            oltType: 'XINGELIN',
            mountPoint: 'GET_LINEPROFILE',
            oltHardVersion,
            view},null,me)
        let msg = resultArr[0].replace(/-{5,}/g, '|').split('|');
        msg.pop()
        console.log(msg)
        for(var i =0;i<msg.length;i++){
          var PID = msg[i].substring(msg[i].indexOf('Index'),msg[i].indexOf('Name')).split(':')[1].trim()
          var Pname = msg[i].substring(msg[i].indexOf('Name'),msg[i].indexOf('Device type')).split(':')[1].trim()
          result.push({
            id:ulid.ulid(),
            PID,
            Pname
          })
        }
        resolve(result)
      } catch (error) {
        reject(error)
      }
    });
  }
  async getonufind_XGL(oltHardVersion,me){
    return new Promise(async (resolve, reject) => {
      let addr = this.options.ip + ":" + this.options.tPort
      let view = {
          username: this.options.username,
          password: this.options.password,
          prompt: this.options.systemName,
          ManagementPassword: this.options.managementPassword,
      }
      try {
        let result = []
        let resultArr = await common.run_EX(addr, {
            oltType: 'XINGELIN',
            mountPoint: 'ONU_FIND',
            oltHardVersion,
            view},null,me)
        let msg = resultArr[0].split('\n')
        for(var i =2;i<msg.length-2;i++){
          var params = msg[i].replace(/\s+/g, '|').split('|')
          result.push({
            PONindex:params[0].split('/')[1],
            ONUindex:params[1],
            SN:params[2],
            state:""
          })
        }
        resolve(result)
      } catch (error) {
        reject(error)
      }
    });
  }
  async saveOlt(oltHardVersion,me){
    return new Promise(async (resolve, reject) => {
      let addr = this.options.ip + ":" + this.options.tPort
      let view = {
          username: this.options.username,
          password: this.options.password,
          prompt: this.options.systemName,
          ManagementPassword: this.options.managementPassword,
      }
      try {
        let resultArr = await common.run_EX(addr, {
            oltType: 'XINGELIN',
            mountPoint: 'SAVE',
            oltHardVersion,
            view},null,me)
        resolve(true)
      } catch (error) {
        reject(error)
      }
    });
  }
  async getOnulist(oltHardVersion,me){
    return new Promise(async (resolve, reject) => {
      let addr = this.options.ip + ":" + this.options.tPort;
      let view = {
        username: this.options.username,
        password: this.options.password,
        prompt: this.options.systemName,
        ManagementPassword: this.options.managementPassword,
      }
      try {
        let resultArray = [];
        let resultArr = await common.run_EX(addr, {
          oltType: 'XINGELIN',
          mountPoint: 'ONU_LIST',
          oltHardVersion,
          view
        },null,me)
        let msg = resultArr[0].split('\n')
        for(var i =2;i<msg.length-2;i++){
          let params = msg[i].replace(/\s+/g, '|').split('|')
          resultArray.push(params[0])
        }
        resolve(resultArray)
      } catch (error) {
        reject(error)
      }
    })
  }
  async getONUDetailInfo(onuArr,oltHardVersion,me){
    return new Promise(async (resolve, reject) => {
      let addr = this.options.ip + ":" + this.options.tPort;
      let view = {
        username: this.options.username,
        password: this.options.password,
        prompt: this.options.systemName,
        ManagementPassword: this.options.managementPassword,
        onuArr
      }
      try {
        let resultArr = await common.run_EX(addr, {
          oltType: 'XINGELIN',
          mountPoint: 'GET_DETAIL_INFO',
          oltHardVersion,
          view
        },null,me)
        let resultArray = []
        resultArr.shift()
        resultArr.forEach(item =>{
          let onlyindex = item.substring(item.indexOf('ONT'),item.indexOf('Description')).split(':')[1].trim()
          let ONUname = item.substring(item.indexOf('Description'),item.indexOf('Type')).split(':')[1].trim()
          let state = item.substring(item.indexOf('Status'),item.indexOf('W/S')).split(':')[1].trim()
          let SN = item.substring(item.indexOf('SN'),item.indexOf('Password')).split(':')[1].trim()
          if(state == 'online'){
            state = 'working'
          }else if(state == 'offline'){
            state = 'OffLine'
          }
          resultArray.push({
            ONUname,
            PONindex: onlyindex.split('/')[1],
            ONUindex: onlyindex.split('/')[2],
            SN,
            onlyindex:onlyindex.split('/')[1]+":"+onlyindex.split('/')[2],
            state,
        });
        })
        resolve(resultArray)
      } catch (error) {
        reject(error)
      }
    })
  }
  async deleteONU(PONindex,ONUindex,oltHardVersion,me){
    return new Promise(async (resolve, reject) => {
      let addr = this.options.ip + ":" + this.options.tPort;
      //组装模板变量
      let view = {
        username: this.options.username,
        password: this.options.password,
        prompt: this.options.systemName,
        ManagementPassword: this.options.managementPassword,
        ONUindex,
        PONindex
      };
      try {
        let resultArr = await common.run_EX(addr, {
          oltType: "XINGELIN",
          mountPoint: "DELETE_ONU",
          oltHardVersion,
          view,
        },null,me);
        resolve(true);
      } catch (error) {
        reject(error);
      }
    });
  }
  async setONU(PONindex,ONUindex,SN,uplink,down,lineProfile,ONUname,oltHardVersion,me){
    return new Promise(async (resolve, reject) => {
      let addr = this.options.ip + ":" + this.options.tPort;
      //组装模板变量
      let view = {
        username: this.options.username,
        password: this.options.password,
        prompt: this.options.systemName,
        ManagementPassword: this.options.managementPassword,
        PONindex,
        ONUindex,
        SN,
        uplink,
        down,
        lineProfile,
        ONUname
      }
      try {
        let fn = function(msg){
          if(msg.indexOf('Error') != -1){
            return {result:false,message:msg.substring(msg.indexOf('Error:'),msg.indexOf('.'))}
          }else if(msg.indexOf('You are modifying an existed profile') != -1){
            return {result:false,message:"The ONT ID has already existed"}
          }else{
            return{result:true}
          }
        }
        let resultArr = await common.run_EX(addr, {
          oltType: 'XINGELIN',
          mountPoint: 'CREATE_ONUFIND',
          oltHardVersion,
          view
        },fn,me)
        if(resultArr.length!= 0){
          resolve(resultArr)
        }else{
          resolve(true)
        }
      } catch (error) {
        reject(error)
      }
    });
  }
  async getUplinkAdminStatusAndVlan(uplinkport,oltHardVersion,me){
    return new Promise(async (resolve, reject) => {
      let addr = this.options.ip + ":" + this.options.tPort;
      //组装模板变量
      let view = {
        username: this.options.username,
        password: this.options.password,
        prompt: this.options.systemName,
        ManagementPassword: this.options.managementPassword,
        uplinkport
      };
      try {
        let resultArr = await common.run_EX(addr, {
          oltType: "XINGELIN",
          mountPoint: "GET_UPLINK_ADMINSTATUS_AND_VLAN",
          oltHardVersion,
          view,
        },null,me);
        let temp = Object.create(null)
        let msg = resultArr[0].split('\n')
        msg.shift()
        msg.pop()
        msg.pop()
        let shutdn = msg[0].indexOf('shutdn')
        let Speed = msg[0].indexOf('Speed')
        let PVID = msg[0].indexOf('PVID')
        let Mode = msg[0].indexOf('Mode')
        let TagVlan = msg[0].indexOf('TagVlan')
        let UtVlan = msg[0].indexOf('UtVlan')
        let adminStatus = msg[1].substring(shutdn,Speed).trim()
        if(adminStatus == 'false'){
          temp.AdminStatus = 1
        }else{
          temp.AdminStatus = 2
        }
        let str = msg[1].substring(TagVlan,UtVlan).trim()
        if(msg.length >= 3){
          for(var i = 2;i<msg.length;i++){
            str += msg[i].trim()
          }
        }
        let arr = str.split(',')
        let arr2 = []
        arr.forEach(item =>{
          if(item != '1'){
            arr2.push(item)
          }
        })
        temp.Tagvlan = arr2.toString()
        let untagvlan = msg[1].substring(PVID,Mode).trim()
        if(untagvlan == "1"){
          temp.UnTagvlan = ''
        }else{
          temp.UnTagvlan = untagvlan
        }
        resolve(temp);
      } catch (error) {
        reject(error);
      }
    });
  }
  async setUplink(portID,adminStatus,addvlan,UnTagvlan,oldUnTagvlan,removevlan,oltHardVersion,me){
    if(adminStatus == 1){
      var type = "no shutdown"
    }else if(adminStatus == 2){
      var type = "shutdown"
    }
    return new Promise(async (resolve, reject) => {
      let addr = this.options.ip + ":" + this.options.tPort;
      //组装模板变量
      let view = {
        username: this.options.username,
        password: this.options.password,
        prompt: this.options.systemName,
        ManagementPassword: this.options.managementPassword,
        portID,
        type,
        addvlan,
        UnTagvlan,
        oldUnTagvlan,
        removevlan
      };
      try {
        let resultArr = await common.run_EX(addr, {
          oltType: "XINGELIN",
          mountPoint: "SET_UPLINK",
          oltHardVersion,
          view,
        },null,me);
        resolve(true);
      } catch (error) {
        reject(error);
      }
    });
  }
}

module.exports = XGLOLT;
